package com.tenement.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.mybatisflex.core.tenant.TenantManager;
import com.tenement.common.GlobalException;
import com.tenement.dto.LoginUserDto;
import com.tenement.entity.Menu;
import com.tenement.entity.User;
import com.tenement.enums.RespBusiness;
import com.tenement.service.MenuService;
import com.tenement.service.UserRoleService;
import com.tenement.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    @Lazy
    private UserService userService;

    @Autowired
    @Lazy
    private MenuService menuService;

    @Autowired
    @Lazy
    private UserRoleService userRoleService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = TenantManager.withoutTenantCondition(() -> userService.byAccount(username));
        if(ObjectUtil.isNull(user)) {
            throw new GlobalException(RespBusiness.NO_USER_EXISTS);
        }
        if (user.getIsActive() == 1) {
            throw new GlobalException(RespBusiness.ACCOUNT_UNAVAILABLE);
        }
        List<Menu> menus = userRoleService.roleMenu(user.getId());
        // 获取权限菜单
        List<Menu> menuList = menus.stream()
                .filter(menu -> menu.getType() != 2).collect(Collectors.toList());
        // 封装菜单
        List<Menu> authMenus = menuList.stream()
                    .filter(menu -> menu.getPId() == 0 || menuList.stream().noneMatch(other -> other.getId().equals(menu.getPId())))
                    .peek(menu -> menu.setChildren(getChildren(menu, menuList)))
                    .collect(Collectors.toList());
        // 设置用户的权限
        List<String> authorities = menus.stream()
                .map(Menu::getPermissionCode)
                .filter(StrUtil::isNotEmpty)
                .distinct()
                .collect(Collectors.toList());
        return new LoginUserDto().setUser(user).setAuthCode(authorities).setAuthMenus(authMenus);
    }

    private List<Menu> getChildren(Menu menu, List<Menu> menus) {
        return menus.stream()
                .filter(child -> child.getPId().equals(menu.getId()))
                .peek(child -> child.setChildren(getChildren(child, menus)))
                .collect(Collectors.toList());
    }

}
